// --------------------------------------------------------------------------------------------------------------------
// <copyright file="SqlAzureAdapterTest.cs" company="">
//   
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace Tests
{
    using System;
    using System.Threading;

    using ExecutionTool.CopyDatabase;
    using ExecutionTool.Profile;

    using Microsoft.Practices.EnterpriseLibrary.Logging;
    using Microsoft.VisualStudio.TestTools.UnitTesting;

    using Moq;

    using Timer = System.Timers.Timer;

    [TestClass]
    public class SqlAzureAdapterTest
    {
        #region Constants

        private const string DatabaseName = "POC";

        private const string Password = "P@ssw)rd";

        private const string ServerNamePrefix = "yj63a5jos3";

        private const string UserName = "devscus";

        #endregion

        #region Fields

        private SqlAzureLocation database;

        #endregion

        #region Public Methods and Operators

        [TestMethod]
        public void CanCheckWhetherDatabaseExistsOrNot()
        {
            var loggerMock = new Mock<LogWriter>();

            var adapter = new SqlAzureAdapter(loggerMock.Object);
            var exists = adapter.DatabaseExists(this.database, this.database.DatabaseName);

            Assert.IsTrue(exists);
        }

        [TestMethod]
        public void CanGetEditionCapacityInfo()
        {
            var loggerMock = new Mock<LogWriter>();

            var adapter = new SqlAzureAdapter(loggerMock.Object);
            var info = adapter.GetDatabaseInfo(this.database);

            Assert.AreEqual(SqlAzureDatabaseEdtion.Web, info.Edition);
            Assert.AreEqual(1, info.MaxSizeInGb);
        }

        [TestMethod]
        public void CanGetOperationProgress()
        {
            var loggerMock = new Mock<LogWriter>();
            var adapter = new SqlAzureAdapter(loggerMock.Object);
            var progress = adapter.GetCopyDatabaseProgress(this.database, "targetDatabaseName");

            Assert.AreEqual(0, progress);
        }

        [TestMethod]
        [Ignore]
        public void IntegrateTest()
        {
            // get Edition and Cap info
            var targetDatabaseName = Guid.NewGuid().ToString("D");
            var adapter = new SqlAzureAdapter();

            TryCatchHelper(
                () =>
                    {
                        var info = adapter.GetDatabaseInfo(this.database);

                        Assert.AreEqual(SqlAzureDatabaseEdtion.Web, info.Edition);
                        Assert.AreEqual(1, info.MaxSizeInGb);
                    });

            // start to copy
            TryCatchHelper(() => adapter.StartCopyDatabase(this.database, targetDatabaseName));

            // monitoring progress
            var wait = new ManualResetEvent(false);
            var timer = new Timer(5000);
            timer.Elapsed += (o, e) =>
                {
                    try
                    {
                        var newProgress = adapter.GetCopyDatabaseProgress(this.database, targetDatabaseName);
                        Console.WriteLine("{0}: {1}%", DateTime.UtcNow, newProgress);

                        if (newProgress < 100)
                        {
                            return;
                        }

                        wait.Set();
                        timer.Dispose();
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex);
                    }
                };

            timer.Enabled = true;
            wait.WaitOne();

            // cleanup
            TryCatchHelper(() => adapter.DeleteDatabase(this.database, targetDatabaseName));
        }

        [TestMethod]
        [Ignore]
        public void IntegrateTestAbort()
        {
            // get Edition and Cap info
            var targetDatabaseName = Guid.NewGuid().ToString("D");
            var adapter = new SqlAzureAdapter();

            TryCatchHelper(
                () =>
                    {
                        var info = adapter.GetDatabaseInfo(this.database);

                        Assert.AreEqual(SqlAzureDatabaseEdtion.Web, info.Edition);
                        Assert.AreEqual(1, info.MaxSizeInGb);
                    });

            // start to copy
            TryCatchHelper(() => adapter.StartCopyDatabase(this.database, targetDatabaseName));

            // monitoring progress
            var wait = new ManualResetEvent(false);
            var timer = new Timer(5000);
            timer.Elapsed += (o, e) =>
                {
                    try
                    {
                        var newProgress = adapter.GetCopyDatabaseProgress(this.database, targetDatabaseName);
                        Console.WriteLine("{0}: {1}%", DateTime.UtcNow, newProgress);

                        if (newProgress <= 0)
                        {
                            return;
                        }

                        wait.Set();
                        timer.Dispose();
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex);
                    }
                };

            timer.Enabled = true;
            wait.WaitOne();

            // abort
            TryCatchHelper(() => adapter.DeleteDatabase(this.database, targetDatabaseName));

            // make sure the target database was dropped
            TryCatchHelper(
                () =>
                    {
                        this.database.DatabaseName = targetDatabaseName;

                        try
                        {
                            adapter.GetDatabaseInfo(this.database);
                        }
                        catch (Exception ex)
                        {
                            Assert.IsTrue(ex.Message.StartsWith("Cannot open database"));
                            return;
                        }

                        Assert.Fail();
                    });
        }

        [TestInitialize]
        public void Setup()
        {
            this.database = new SqlAzureLocation
                {
                   ServerNamePrefix = ServerNamePrefix, UserName = UserName, Password = Password, DatabaseName = DatabaseName, 
                };
        }

        #endregion

        #region Methods

        private static void TryCatchHelper(Action action)
        {
            try
            {
                action();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
                Assert.Fail();
            }
        }

        #endregion
    }
}
